#include "tcpsocket.h"
#include <stdio.h>  
#include <stdlib.h>  
#include <errno.h>  
#include <string.h>  
#include <sys/types.h>  
#include <netinet/in.h>  
#include <sys/socket.h>  
#include <sys/wait.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <openssl/ssl.h>  
#include <openssl/err.h>  
#include <fcntl.h>  
#include <sys/epoll.h>  
#include <sys/time.h>  
#include <sys/resource.h>  
#define MAXBUF 1024  
#define MAXEPOLLSIZE 1000  
/* 
   setnonblocking - ÉèÖÃ¾ä±úÎª·Ç×èÈû·½Ê½ 
 */  
int setnonblocking(int sockfd)  
{  
	if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)  
	{  
		return -1;  
	}  
	return 0;  
}  
/* 
   handle_message - ´¦ÀíÃ¿¸ö socket ÉÏµÄÏûÏ¢ÊÕ·¢ 
 */  
int handle_message(int new_fd)  
{  
	char buf[MAXBUF + 1];  
	int len;  

	/* ¿ªÊ¼´¦ÀíÃ¿¸öÐÂÁ¬½ÓÉÏµÄÊý¾ÝÊÕ·¢ */  
	bzero(buf, MAXBUF + 1);  

	/* ½ÓÊÕ¿Í»§¶ËµÄÏûÏ¢ */  
	len = recv(new_fd, buf, MAXBUF, 0);  
	if (len > 0)  
	{  
		printf  
			("%d½ÓÊÕÏûÏ¢³É¹¦:'%s'£¬¹²%d¸ö×Ö½ÚµÄÊý¾Ý\n",  
			 new_fd, buf, len);  
	}  
	else  
	{  
		if (len < 0)  
			printf  
				("ÏûÏ¢½ÓÊÕÊ§°Ü£¡´íÎó´úÂëÊÇ%d£¬´íÎóÐÅÏ¢ÊÇ'%s'\n",  
				 errno, strerror(errno));  
		close(new_fd);  
		return -1;  
	}  
	/* ´¦ÀíÃ¿¸öÐÂÁ¬½ÓÉÏµÄÊý¾ÝÊÕ·¢½áÊø */  
	return len;  
}  
int main(int argc, char **argv)  
{  
	int listener, new_fd, kdpfd, nfds, n, ret, curfds;  
	socklen_t len;  
	struct sockaddr_in my_addr, their_addr;  
	unsigned int myport, lisnum;  
	struct epoll_event ev;  
	struct epoll_event events[MAXEPOLLSIZE];  
	struct rlimit rt;  
	myport = 5000;  
	lisnum = 2;   

	/* ÉèÖÃÃ¿¸ö½ø³ÌÔÊÐí´ò¿ªµÄ×î´óÎÄ¼þÊý */  
	rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;  
	if (setrlimit(RLIMIT_NOFILE, &rt) == -1)   
	{  
		perror("setrlimit");  
		exit(1);  
	}  
/*
	if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)  
	{  
		perror("socket");  
		exit(1);  
	}  

	setnonblocking(listener);  
	bzero(&my_addr, sizeof(my_addr));  
	my_addr.sin_family = PF_INET;  
	my_addr.sin_port = htons(myport);  
	my_addr.sin_addr.s_addr = INADDR_ANY;  
	if (bind(listener, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)   
	{  
		perror("bind");  
		exit(1);  
	}   
	if (listen(listener, lisnum) == -1)   
	{  
		perror("listen");  
		exit(1);  
	}  
*/
	TcpSocket svr("127.0.0.1",myport);
	svr.Bind();
	svr.Listen();
	listener = svr.GetSocketFD();	
	/* ´´½¨ epoll ¾ä±ú£¬°Ñ¼àÌý socket ¼ÓÈëµ½ epoll ¼¯ºÏÀï */  
	kdpfd = epoll_create(MAXEPOLLSIZE);  
	len = sizeof(struct sockaddr_in);  
	ev.events = EPOLLIN;  
	ev.data = &svr;  
	if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0)   
	{  
		fprintf(stderr, "epoll set insertion error: fd=%d\n", listener);  
		return -1;  
	}  
	curfds = 1;  
	while (1)   
	{  
		/* µÈ´ýÓÐÊÂ¼þ·¢Éú */  
		nfds = epoll_wait(kdpfd, events, curfds, -1);  
		if (nfds == -1)  
		{  
			perror("epoll_wait");  
			break;  
		}  
		/* ´¦ÀíËùÓÐÊÂ¼þ */  
		for (n = 0; n < nfds; ++n)  
		{  
			if (TcpSocket*(events[n].data) == &svr)   
			{  
				//new_fd = accept(listener, (struct sockaddr *) &their_addr,&len);  
				new_fd = svr.Accept();
				if (new_fd < 0)   
				{  
					perror("accept");  
					continue;  
				}   
				else  
				{  
					printf("accept a new socket %d:%d the socket fd is %d\n",  
							inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);  
				}  
				setnonblocking(new_fd);  
				ev.events = EPOLLIN | EPOLLET;  
				ev.data.fd = new_fd;  
				if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, new_fd, &ev) < 0)  
				{  
					fprintf(stderr, "°Ñ socket '%d' ¼ÓÈë epoll Ê§°Ü£¡%s\n",  
							new_fd, strerror(errno));  
					return -1;  
				}  
				curfds++;  
			}   
			else  
			{  
				printf("client socket is happen\n");
				//				ret = handle_message(events[n].data.fd);  
				//				if (ret < 1 && errno != 11)  
				//				{  
				//					epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);  
				//					curfds--;  
				//				}  
			}  
		}  
	}  
	close(listener);  
	return 0;  
}  

